package com.fist.eth.flutter_plugin_eth_wallet

import android.util.Log
import android.widget.Toast
import com.fist.eth.flutter_plugin_eth_wallet.utils.TokenContract
import com.fist.eth.flutter_plugin_eth_wallet.utils.TokenContractUtils
import com.fist.eth.flutter_plugin_eth_wallet.utils.TokenManager
import com.fist.eth.flutter_plugin_eth_wallet.utils.WalletUtils
import io.flutter.plugin.common.MethodChannel
import io.reactivex.Single
import io.reactivex.SingleObserver
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import org.web3j.crypto.CipherException
import org.web3j.crypto.Keys
import org.web3j.protocol.core.methods.response.TransactionReceipt
import java.lang.Exception
import java.math.BigInteger
import java.util.concurrent.*

object ContractUtils {

    private fun getContract(): TokenContract {
        val manage = TokenManager.instance
        val wallet = manage.wallet!!
        if (manage.contract == null)
            manage.setContract(TokenContractUtils.loadContract(wallet, gasPrice, gasLimit))

        return manage.contract!!
    }

    fun transfer(password: String, toAddress: String, value: BigInteger): Future<Result> {
        var result = Result()
        val wallet = TokenManager.instance.wallet!!
        try {
            WalletUtils.loadCredentials(password, wallet.walletFile)
            getContract().transfer(toAddress, value).sendAsync().get()


        } catch (e: CipherException) {
            Log.e("密码错误", e.message)
            e.printStackTrace()
            result = Result("密码错误")
        } catch (e: Exception) {
            result = Result(e.message!!)
        }

        return object : Future<Result> {
            override fun cancel(b: Boolean): Boolean {
                return false
            }

            override fun isCancelled(): Boolean {
                return false
            }

            override fun isDone(): Boolean {
                return false
            }

            @Throws(InterruptedException::class, ExecutionException::class)
            override fun get(): Result {
                return result
            }

            @Throws(InterruptedException::class, ExecutionException::class, TimeoutException::class)
            override fun get(l: Long, timeUnit: TimeUnit): Result {
                return result
            }
        }
    }

    //         password: String   val credentials = WalletUtils.loadCredentials(password, wallet!!.walletFile)

    fun balance(): Future<BigInteger> {
        return getContract().balanceOf(Keys.toChecksumAddress(TokenManager.instance.wallet!!.address)).sendAsync()
    }

    fun balance(result: MethodChannel.Result) {
        val wallet = TokenManager.instance.wallet!!
        val addr1 = wallet.address
        val addr2 = wallet.walletFile.address

        Log.e("address", "$addr1 ; $addr2")

        Single.fromCallable {
            getContract().balanceOf(addr1)
                    .send()
        }
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(object : SingleObserver<BigInteger> {
                    override fun onSubscribe(d: Disposable) {}

                    override fun onSuccess(bigInteger: BigInteger) {
                        Log.i("TAG", "onClickGetBalance: $bigInteger")
                        result.success(bigInteger.toString())
                    }

                    override fun onError(e: Throwable) {
                        e.printStackTrace()
                    }
                })
    }

    val gasPrice: BigInteger get() = BigInteger("100000000000")
    val gasLimit: BigInteger get() = BigInteger.valueOf(600000)


}